﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace Leaf.NetCore.HotUpdate
{
    public class XMLHelper
    {
        #region 反序列化

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="xml">XML字符串</param>
        /// <returns></returns>
        public static T XmlDeserialize<T>(string xml)
        {
            try
            {
                using (StringReader sr = new StringReader(xml))
                {
                    XmlSerializer xmldes = new XmlSerializer(typeof(T));
                    return (T)xmldes.Deserialize(sr);
                }
            }
            catch
            {
                return default(T);
            }
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="type"></param>
        /// <param name="xml"></param>
        /// <returns></returns>
        private static object Deserialize(Type type, Stream stream)
        {
            XmlSerializer xmldes = new XmlSerializer(type);
            return xmldes.Deserialize(stream);
        }

        #endregion 反序列化

        #region 序列化XML文件

        /// <summary>
        /// 序列化XML文件
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="obj">对象</param>
        /// <returns></returns>

        public static string XmlSerializer<T>(T t)
        {
            MemoryStream Stream = new MemoryStream();
            //创建序列化对象
            XmlSerializer xml = new XmlSerializer(t.GetType());
            try
            {
                //序列化对象
                xml.Serialize(Stream, t);
            }
            catch (InvalidOperationException)
            {
                throw;
            }

            Stream.Position = 0;
            StreamReader sr = new StreamReader(Stream);
            string str = sr.ReadToEnd();
            return str;
        }

        #endregion 序列化XML文件

        #region 获取对应XML节点的值

        /// <summary>
        /// 摘要:获取对应XML节点的值
        /// </summary>
        /// <param name="stringRoot">XML节点的标记</param>
        /// <returns>返回获取对应XML节点的值</returns>

        public static string XmlAnalysis(string stringRoot, string xml)
        {
            if (stringRoot.Equals("") == false)
            {
                try
                {
                    XmlDocument XmlLoad = new XmlDocument();
                    XmlLoad.LoadXml(xml);
                    return XmlLoad.DocumentElement.SelectSingleNode(stringRoot).InnerXml.Trim();
                }
                catch
                {
                }
            }
            return "";
        }

        #endregion 获取对应XML节点的值

        /// <summary>
        /// 将实体转换为XML节点对象 属性变为 attribute=value
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="list">实体</param>
        /// <returns>XElement</returns>
        public static XElement GetXmlElementFromObject<T>(IEnumerable<T> list, string name = "", string typeExt = "List")
        {
            if (list == null || list.Count() < 0)
                return null;
            T obj = list.ElementAt(0);
            Type type = obj.GetType();
            string typeName = string.IsNullOrEmpty(name) ? type.Name : name;
            typeName += typeExt;
            XElement es = new XElement(typeName);
            foreach (var item in list)
            {
                var e = GetXmlElementFromObject<T>(item, name);
                es.Add(e);
            }
            return es;
        }

        /// <summary>
        /// 将实体转换为XML节点对象 属性变为 attribute=value
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="obj">实体</param>
        /// <returns>XElement</returns>
        public static XElement GetXmlElementFromObject<T>(T obj, string name = "")
        {
            if (obj == null)
                return null;
            Type type = obj.GetType();
            PropertyInfo[] ps = type.GetProperties();
            name = string.IsNullOrEmpty(name) ? type.Name : name;
            XElement e = new XElement(name);
            foreach (var item in ps)
            {
                object o = item.GetValue(obj, null);
                if (o == null)
                    o = "";
                e.Add(new XAttribute(item.Name, o.ToString()));
            }
            return e;
        }

        #region Xml插入数据

        /// <summary>
        /// Xml指定节点元素属性插入数据
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="node">节点</param>
        /// <param name="element">元素名</param>
        /// <param name="attribute">属性名</param>
        /// <param name="value">属性数据</param>
        /// <returns></returns>
        /**************************************************
         * 使用示列:
         * XmlHelper.XmlInsertValue(path, "/books", "book", "author", "Value")
         ************************************************/

        public static void XmlInsertValue(string path, string node, string element, string attribute, string value)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNode xmlNode = doc.SelectSingleNode(node);
                if (element.Equals(""))
                {
                    if (!attribute.Equals(""))
                    {
                        XmlElement xe = (XmlElement)xmlNode;
                        xe.SetAttribute(attribute, value);
                    }
                }
                else
                {
                    XmlElement xe = doc.CreateElement(element);
                    if (attribute.Equals(""))
                        xe.InnerText = value;
                    else
                        xe.SetAttribute(attribute, value);
                    //添加新增的节点
                    xmlNode.AppendChild(xe);
                }

                //保存Xml文档
                doc.Save(path);
            }
            catch { }
        }

        #endregion Xml插入数据

        #region Xml修改数据

        /// <summary>
        /// Xml指定节点元素属性修改数据
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="node">节点</param>
        /// <param name="attribute">属性名</param>
        /// <param name="value">属性数据</param>
        /// <returns></returns>
        /**************************************************
         * 使用示列:
         * XmlHelper.XmlUpdateValue(path, "/books", "book","author","Value")
         ************************************************/

        public static void XmlUpdateValue(string path, string node, string attribute, string value)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNode xmlNode = doc.SelectSingleNode(node);
                XmlElement xmlElement = (XmlElement)xmlNode;
                if (attribute.Equals(""))
                    xmlElement.InnerText = value;
                else
                    xmlElement.SetAttribute(attribute, value);

                //保存Xml文档
                doc.Save(path);
            }
            catch { }
        }

        #endregion Xml修改数据

        #region Xml删除数据

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="node">节点</param>
        /// <param name="attribute">属性名</param>
        /// <returns></returns>
        /**************************************************
         * 使用示列:
         * XmlHelper.XmlDelete(path, "/books", "book")
         ************************************************/

        public static void XmlDelete(string path, string node, string attribute)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(path);
                XmlNode xn = doc.SelectSingleNode(node);
                XmlElement xe = (XmlElement)xn;
                if (attribute.Equals(""))
                    xn.ParentNode.RemoveChild(xn);
                else
                    xe.RemoveAttribute(attribute);
                doc.Save(path);
            }
            catch { }
        }

        #endregion Xml删除数据
    }
}